#include "stdinc.h"
#include <Ogre.h>

#include "Creatures.h"
#include "DwarfFort/InternalStructures.h"
#include "DwarfFort/Interface.h"
#include "Main/Logger.h"
#include "Main/App.h"

#include "GUI/DwarfGUI.h"
#include "GUI/Cutaway.h"

// dorf == 0xa6

using namespace Graphics;
using namespace Ogre;

CreatureManager::CreatureManager(SceneManager *sceneManager)
								 :StateListener(DwarfFort::GS_INGAME),
								  mSceneManager(sceneManager)
								 
{
}

void CreatureManager::stateCreated()
{
	mOriginalCreatures = (std::hacked_vector<DwarfFort::Creature*> *) 0x01583224;

	Animation::setDefaultInterpolationMode(Animation::IM_LINEAR);
    Animation::setDefaultRotationInterpolationMode(Animation::RIM_LINEAR);

	
	SkeletonPtr skel = SkeletonManager::getSingleton().load("Dorf_mesh.skeleton", 
		ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	Animation* anim = skel->getAnimation("Walk");
	
	Animation::NodeTrackIterator trackIter = anim->getNodeTrackIterator();
	while (trackIter.hasMoreElements())
	{
		NodeAnimationTrack* track = trackIter.getNext();
		TransformKeyFrame* newKf = track->createNodeKeyFrame(anim->getLength());
		TransformKeyFrame* startKf = track->getNodeKeyFrame(0);
		newKf->setRotation(startKf->getRotation());
		newKf->setTranslate(startKf->getTranslate());
		newKf->setScale(startKf->getScale());
	}

	std::hacked_vector<DwarfFort::Creature*>::iterator i = mOriginalCreatures->begin();
	for (;i != mOriginalCreatures->end(); i++)
	{
		if ((*i)->race == 0xa6) // dorf here
		{
			CreatureModel *model = new CreatureModel(mSceneManager,(*i));
			mCreatures.push_back(model);
		}
	}
}

void CreatureManager::cleanup()
{
	if (!mCreatures.empty())
	{
		std::vector<CreatureModel*>::iterator i = mCreatures.begin();
		for (;i!= mCreatures.end();i++)
			delete (*i);
	}
}
CreatureManager::~CreatureManager()
{
	cleanup();
}

void CreatureManager::stateUpdate(int level)
{
	if (!mCreatures.empty())
	{
		std::vector<CreatureModel*>::iterator i = mCreatures.begin();
		for (;i!= mCreatures.end();i++)
			(*i)->update();
	}
}

int hackie = 0;

CreatureModel::CreatureModel(Ogre::SceneManager *parentManager, DwarfFort::Creature *original)
							:mOriginalData(original)
{
	mContainerNode = parentManager->getRootSceneNode()->createChildSceneNode();
	mCreatureModel = parentManager->createEntity(Ogre::String("Dorf_")+mOriginalData->name.c_str()+
												 Ogre::StringConverter::toString(hackie++),"dorf_mesh.mesh" );
	mContainerNode->setScale(0.01f,0.01f,0.01f);
	mContainerNode->setPosition(mOriginalData->x, 
								mOriginalData->z*2, 
								mOriginalData->y);
	
	if (!mOriginalData->pathX.empty() || 
		!mOriginalData->pathY.empty())
	{
		int dx = mOriginalData->pathX[0] - mOriginalData->x;
		int dy = mOriginalData->pathY[0] - mOriginalData->y;
		Vector3 x(dx,0,dy);
		Vector3 z(-dy,0,dx);
		Vector3 y(0,1,0);
		Quaternion q(x,y,z);
		mContainerNode->setOrientation(q);
	}
		

	mContainerNode->attachObject(mCreatureModel);
	mAnimState  = mCreatureModel->getAnimationState("Walk");
	if (mOriginalData->flags4 & 2) 
	{
		mContainerNode->rotate(Vector3(1,0,0),Degree(90));
		mAnimState->setEnabled(false);
	}
	else
		mAnimState->setEnabled(true);
	mLastTime = Root::getSingleton().getTimer()->getMilliseconds()/1000.0f; 
}

void CreatureModel::update()
{
	int cutawayLevel = Main::App::getSingleton().getGUI()->getCutawayControler()->getCutawayLevel();
	int maxZ = DwarfFort::Interface::getSingleton().getMapCellList()->getZSize();
	if (mOriginalData->z > 1+maxZ - cutawayLevel)
	{
		mContainerNode->setVisible(false);
		return;
	}
	else
		mContainerNode->setVisible(true);

	Real time = Ogre::Root::getSingleton().getTimer()->getMilliseconds()/1000.0f; 
	Real timeDelta = time - mLastTime;
	mLastTime = time;
	if (mOriginalData->flags4 & 2) 
	{
		mAnimState->setEnabled(false);
		return;
	}
	
	mAnimState->addTime(timeDelta);
	mContainerNode->setPosition(mOriginalData->x, 
								mOriginalData->z*2, 
								mOriginalData->y);
	if (!mOriginalData->pathX.empty() || 
		!mOriginalData->pathY.empty())
	{
		int dx = mOriginalData->pathX[0] - mOriginalData->x;
		int dy = mOriginalData->pathY[0] - mOriginalData->y;
		Vector3 x(dx,0,dy);
		Vector3 z(-dy,0,dx);
		Vector3 y(0,1,0);
		Quaternion q(x,y,z);
		mContainerNode->setOrientation(q);
	}
	
}
